/*
 * Creado por NIN
 * User: sebastian.lucas
 * Date: 19/04/2007
 * Time: 9:17
 */

using System;
using System.Drawing;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.Collections.Generic;
using System.Windows.Forms;

namespace CSE
{
	/*
	 * Workspace
	 */
	public class Workspace
	{
		/*
		 * Constants
		 */
	    public static readonly int TYPE_NONE = 0;
	    public static readonly int TYPE_SPRITE = 1;
	    
	    public static readonly int TYPE_CLIP = 0;
	    public static readonly int TYPE_ANIMCLIP = 1;
	    
	    public static readonly string CLIP_NAME_NONAME = "Clip: (null)";
	    public static readonly string CLIP_NAME_NAME   = "Clip: ";
	    
	    /*
	     * Load/Save
	     */
	    // Xml tag for node, e.g. 'node' in case of <node></node>
		private static readonly string TAGNODE = "node";
		private static readonly string TAGFRAMENODE = "frame_node";
		
		// Xml attributes for node
		private static readonly string TAGTEXTATT = "text";
		private static readonly string TAGNAMEATT = "name";
		private static readonly string TAGALIASATT = "alias";
		private static readonly string TAGTYPEATT = "type";
		private static readonly string TAGUSEBITMAPATT = "usebitmap";
		private static readonly string TAGIMGIATT = "imageindex";
		
		private static readonly string TAGXATT = "x";
		private static readonly string TAGYATT = "y";
		private static readonly string TAGWATT = "width";
		private static readonly string TAGHATT = "height";
		
		private static readonly string TAGFRAMEIDATT = "frame_sub_id";
		private static readonly string TAGFRAMEXATT = "frame_sub_x";
		private static readonly string TAGFRAMEYATT = "frame_sub_y";
		private static readonly string TAGFRAMESTARTATT = "frame_sub_start";
		private static readonly string TAGFRAMEENDATT = "frame_sub_end";
		
		// private static readonly string TAGBITMAPATT = "bitmap";
		
	    /*
	     * Variables
	     */
        public static int type = TYPE_NONE;
        
        public static string project_path = "";
        
        public static Bitmap bitmap = null;
        public static string bitmap_path = "";
        
        public static Clip _root;
        public static Clip _library;
        
        public static int libClips_id_gen = 0; // this is really stupid
	    
        /*
         * Init
         */
        public static void Init ()
        {
            type = TYPE_NONE;
            
            /*
             * Hardcoded for now
             */
            type = TYPE_SPRITE;
            MainForm.self.MainFormSetDefaults();
            
            SetDefaults ();
            Stage.Init();
        }
        
        /*
         * Shutdown
         */
        public static void Shutdown ()
        {
            if (type != TYPE_NONE)
            {
            	Stage.Shutdown();
            }
            
            type = TYPE_NONE;
        }
        
        /*
         * SetSourceBitmap
         */
        public static void SetSourceBitmap (string str)
        {
        	if (type == TYPE_NONE)
        	{
        		return;
        	}
        	
        	if (bitmap != null)
        	{
        		bitmap = null;
        	}
        	
        	bitmap_path = str;
        	bitmap = new Bitmap(Bitmap.FromFile(project_path + str));
        }
        
        /*
         * SetDefaults
         */
        private static void SetDefaults ()
        {
        	if (type == TYPE_SPRITE)
        	{
        		_root = new Clip("_root", false);
        		_library = new Clip("_library", false);
        		
        		MainForm.libClipsRoot.Tag = _root;
        		MainForm.libClipsLibrary.Tag = _library;
        	}
        	
        	project_path = "";
        	libClips_id_gen = 0;
        }
        
        /*
         * SetPath
         */
        public static void SetPath (string path)
        {
            project_path = path;
        }
        
        /*
         * GetKey
         */
        public static int GetKey ()
        {
        	return libClips_id_gen++;
        }
        
        /*
         * NewClip
         */
        public static TreeNode NewClip (int type, string name, bool usebitmap)
        {
        	Clip nc = new Clip(name, usebitmap);
        	nc.type = type;
        	TreeNode nt = MainForm.libSel.Nodes.Add(Workspace.GetKey().ToString() + "_clip", name, type, type);
        	
        	if (usebitmap)
        	{
        		nt.SelectedImageIndex = nt.ImageIndex = MainForm.ICON_CLIP_BITMAP;
        	}
        	else if (type == Workspace.TYPE_CLIP)
        	{
        		nt.SelectedImageIndex = nt.ImageIndex = MainForm.ICON_CLIP_STATIC;
        	}
        	else if (type == Workspace.TYPE_ANIMCLIP)
        	{
        		nt.SelectedImageIndex = nt.ImageIndex = MainForm.ICON_CLIP_ANIM;
        	}
        	
        	nt.Tag = nc;
        	MainForm.libSel.Expand();
        	return nt;
        }
        
        /*
         * GetClipFromName
         */
        public static Clip GetClipFromName (string name)
        {
            TreeNodeCollection nodesCollection = MainForm.libClipsLibrary.Nodes;
            Clip ret = null;
            
        	for(int i = 0; i < nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            ret = ((Clip)node.Tag);
	            
	            if (ret.name == name)
	            {
	                return ret;
	            }
			}
        	
        	return null;
		}
        
        /*
         * SortLibrary
         */
        public static void SortLibrary ()
        {
            int i=0;
            TreeNodeCollection nodesCollection = MainForm.libClipsLibrary.Nodes;
            List<TreeNode> modules = new List<TreeNode>();
            List<TreeNode> frames = new List<TreeNode>();
            List<TreeNode> animations = new List<TreeNode>();
            
            MainForm.TreeView.BeginUpdate();
            
            for (i=0; i<nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            Clip _clip = ((Clip)node.Tag);
	            
	            if (_clip.usebitmap)
	            {
	                modules.Add(node);
	            }
	            else if (_clip.type == Workspace.TYPE_CLIP)
	            {
	                frames.Add(node);
	            }
	            else if (_clip.type == Workspace.TYPE_ANIMCLIP)
	            {
	                animations.Add(node);
	            }
            }
            
            MainForm.libClipsLibrary.Nodes.Clear();
            
            for (i=0; i<modules.Count; i++) MainForm.libClipsLibrary.Nodes.Add(modules[i]);
            for (i=0; i<frames.Count; i++) MainForm.libClipsLibrary.Nodes.Add(frames[i]);
            for (i=0; i<animations.Count; i++) MainForm.libClipsLibrary.Nodes.Add(animations[i]);
            
            modules = null;
            frames = null;
            animations = null;
            
            MainForm.TreeView.EndUpdate();
        }
        
        /*
         * IsValidClipName
         */
        public static bool IsValidClipName (string name)
        {
            TreeNodeCollection nodesCollection = MainForm.libClipsLibrary.Nodes;
            Clip ret = null;
            int i = 0;
            
            if (name.Length < 1)
            {
                Utils.MsgBox("Please, put at least one name for this clip!");
                return false;
            }
            
            if (name.IndexOfAny(new char[]{'\\', '/', ':', '*', '?', '"', '<', '>', '|'})!=-1)
            {
                Utils.MsgBox("The tree node label must not contain following characters:\n \\ / : * ? \" < > |");
                return false;
            }
            
        	for(i=0; i<nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            ret = ((Clip)node.Tag);
	            
	            if (ret.name == name)
	            {
	                Utils.MsgBox("The new clip must have another name!");
	                return false;
	            }
			}
        	
        	return true;
		}
        
        public static bool AddClip (int _type, string name, bool usebitmap, Rectangle r)
        {
            if (type == TYPE_NONE)
            {
                return false;
            }
            
            MainForm.libSel = MainForm.libClipsLibrary;
        	TreeNode nt = NewClip(_type, name, usebitmap);
        	((Clip)nt.Tag).r.X = r.X;
        	((Clip)nt.Tag).r.Y = r.Y;
        	((Clip)nt.Tag).r.Width = r.Width;
        	((Clip)nt.Tag).r.Height = r.Height;
        	
        	return true;
        }
        
        /*
         * --------------------------------------------------------------------------------------------
         */
        
        /*
         * SaveNodes
         */
        private static void SaveNodes(TreeNodeCollection nodesCollection, 
					XmlTextWriter textWriter)
  		{
            int i = 0;
            int j = 0;
            
        	for(i = 0; i < nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            textWriter.WriteStartElement(TAGNODE);
	            textWriter.WriteAttributeString(TAGNAMEATT, node.Name);
	            textWriter.WriteAttributeString(TAGTEXTATT, node.Text);
	            textWriter.WriteAttributeString(TAGIMGIATT, node.ImageIndex.ToString());
	            if(node.Tag != null)
	            {
	            	textWriter.WriteAttributeString(TAGALIASATT, ((Clip)node.Tag).name);
	            	textWriter.WriteAttributeString(TAGTYPEATT, ((Clip)node.Tag).type.ToString());
	            	textWriter.WriteAttributeString(TAGUSEBITMAPATT, ((Clip)node.Tag).usebitmap.ToString());
	            	
	            	textWriter.WriteAttributeString(TAGXATT, ((Clip)node.Tag).r.X.ToString());
	            	textWriter.WriteAttributeString(TAGYATT, ((Clip)node.Tag).r.Y.ToString());
	            	textWriter.WriteAttributeString(TAGWATT, ((Clip)node.Tag).r.Width.ToString());
	            	textWriter.WriteAttributeString(TAGHATT, ((Clip)node.Tag).r.Height.ToString());
	            	
	            	for (j=0; j<((Clip)node.Tag).childs.Count; j++)
	            	{
	            	    textWriter.WriteStartElement(TAGFRAMENODE);
	            	        textWriter.WriteAttributeString(TAGFRAMEIDATT, ((Clip)node.Tag).childs[j].name);
	            	        textWriter.WriteAttributeString(TAGFRAMEXATT, ((Clip)node.Tag).childs[j].x.ToString());
	            	        textWriter.WriteAttributeString(TAGFRAMEYATT, ((Clip)node.Tag).childs[j].y.ToString());
	            	        textWriter.WriteAttributeString(TAGFRAMESTARTATT, ((Clip)node.Tag).childs[j].start.ToString());
	            	        textWriter.WriteAttributeString(TAGFRAMEENDATT, ((Clip)node.Tag).childs[j].end.ToString());
	            	    textWriter.WriteEndElement();
	            	}
	            }
	            // add other node properties to serialize here  
	            if (node.Nodes.Count > 0)
				{
					SaveNodes(node.Nodes, textWriter);
				}
				textWriter.WriteEndElement();
			}
		}

        /*
         * Save
         */
        public static void Save (string name) 
		{
        	TreeView treeView = MainForm.TreeView;
			XmlTextWriter textWriter = new XmlTextWriter(name, 
                                     System.Text.Encoding.ASCII);
			
        	// writing the xml declaration tag
			textWriter.WriteStartDocument();
			// textWriter.WriteRaw("\r\n");
			// writing the main tag that encloses all node tags
			textWriter.WriteStartElement("Sprite");
       
			// save the nodes, recursive method
			SaveNodes(treeView.Nodes, textWriter);
       
			textWriter.WriteEndElement();
        	 
       		textWriter.Close();
  		}
        
        /*
         * --------------------------------------------------------------------------------------------
         */
        
        private static bool loadbitmap = false;
        private static ClipChild cc = null;
        private static TreeNode temp_node = null;
        
        /*
         * SetAttributeValue
         */
        private static void SetAttributeValue(TreeNode node, 
                     string propertyName, string value)
		{
            if (propertyName == TAGTEXTATT)
			{
				if (value == "_root")
				{
					MainForm.libClipsRoot = node;
				}
				else if (value == "Library")
				{
					MainForm.libClipsLibrary = node;
				}
				else if (value == "Bitmap")
				{
					MainForm.libBitmap = node;
				}
				
				if (loadbitmap)
				{
					Workspace.SetSourceBitmap(value);
					loadbitmap = false;
				}
				
				node.Text = value;
				node.Tag = new Clip(node.Text, false);
				temp_node = node;
			}
			else if (propertyName == TAGNAMEATT)
			{
				node.Name = value;
				
				if (value == "_bitmap_source")
				{
				    MainForm.libBitmapSource = node;
					loadbitmap = true;
				}
			}
			else if (propertyName == TAGIMGIATT) 
			{
				/*node.ImageIndex = int.Parse(value);
				node.SelectedImageIndex = int.Parse(value);*/
			}
			else if (propertyName == TAGALIASATT)
			{
				((Clip)node.Tag).name = value;
			}
			else if (propertyName == TAGTYPEATT)
			{
				((Clip)node.Tag).type = int.Parse(value);
				
				if (!((Clip)node.Tag).usebitmap
                && ((Clip)node.Tag).type == Workspace.TYPE_CLIP)
				{
				    node.ImageIndex = MainForm.ICON_CLIP_STATIC;
			        node.SelectedImageIndex = MainForm.ICON_CLIP_STATIC;
				}
				else if (((Clip)node.Tag).type == Workspace.TYPE_ANIMCLIP)
				{
				    node.ImageIndex = MainForm.ICON_CLIP_ANIM;
			        node.SelectedImageIndex = MainForm.ICON_CLIP_ANIM;
				}
			}
			else if (propertyName == TAGXATT)
			{
				((Clip)node.Tag).r.X = int.Parse(value);
			}
			else if (propertyName == TAGYATT)
			{
				((Clip)node.Tag).r.Y = int.Parse(value);
			}
			else if (propertyName == TAGWATT)
			{
				((Clip)node.Tag).r.Width = int.Parse(value);
			}
			else if (propertyName == TAGHATT)
			{
				((Clip)node.Tag).r.Height = int.Parse(value);
			}
			else if (propertyName == TAGUSEBITMAPATT)
			{
			    if (value.ToUpper() == "TRUE")
			    {
			        ((Clip)node.Tag).usebitmap = true;
			        node.ImageIndex = MainForm.ICON_CLIP_BITMAP;
			        node.SelectedImageIndex = MainForm.ICON_CLIP_BITMAP;
			    }
			}
			else if (propertyName == TAGFRAMEIDATT)
			{
			    cc.name = value;
			}
			else if (propertyName == TAGFRAMEXATT)
			{
			    cc.x = int.Parse(value);
			}
			else if (propertyName == TAGFRAMEYATT)
			{
			    cc.y = int.Parse(value);
			}
			else if (propertyName == TAGFRAMESTARTATT)
			{
			    cc.start = int.Parse(value);
			}
			else if (propertyName == TAGFRAMEENDATT)
			{
			    cc.end = int.Parse(value);
			    
			    if (temp_node != null)
			    {
			        ((Clip)temp_node.Tag).childs.Add(new ClipChild(cc.x, cc.y, cc.name, cc.start, cc.end));
			    }
			}
        }


        /*
         * Load
         */
        public static void Load (string name)
		{
			TreeView treeView = MainForm.TreeView;
			
			cc = new ClipChild(0,0,"",0,0);
			MainForm.libAbs.Clear();
			
			XmlTextReader reader = null;
			try
			{
				// disabling re-drawing of treeview till all nodes are added
		        treeView.BeginUpdate();    
		        reader = new XmlTextReader(name);
		        TreeNode parentNode = null;
		        int i=0;
		        bool isEmptyElement=false;
		        int attributeCount=-1;
		        
		        while (reader.Read())
		        {
		             if (reader.NodeType == XmlNodeType.Element)
		             {      
		                  if (reader.Name == TAGNODE)
		                  {
		                       TreeNode newNode = new TreeNode();
		                       isEmptyElement = reader.IsEmptyElement;
		                
		                       // loading node attributes
		                       attributeCount = reader.AttributeCount;
		                       if (attributeCount > 0)
		                       {
		                          for (i=0; i < attributeCount; i++)
		                          {
		                              reader.MoveToAttribute(i);
		                              SetAttributeValue(newNode, 
		                                           reader.Name, reader.Value);
		                          }        
		                       }
		                       
		                       // add new node to Parent Node or TreeView
		                       if(parentNode != null)
		                          parentNode.Nodes.Add(newNode);
		                       else
		                          treeView.Nodes.Add(newNode);
		                
		                       // making current node 'ParentNode' if its not empty
		                       if (!isEmptyElement)
		                       {
		                          parentNode = newNode;
		                       }
		                  }
		                  else if (reader.Name == TAGFRAMENODE)
		                  {
                                TreeNode newNode = new TreeNode();
		                       isEmptyElement = reader.IsEmptyElement;
		                
		                       // loading node attributes
		                       attributeCount = reader.AttributeCount;
		                       if (attributeCount > 0)
		                       {
		                          for (i = 0; i < attributeCount; i++)
		                          {
		                              reader.MoveToAttribute(i);
		                              SetAttributeValue(newNode, 
		                                           reader.Name, reader.Value);
		                          }        
		                       }
		                       
		                       // making current node 'ParentNode' if its not empty
		                       if (!isEmptyElement)
		                       {
		                          parentNode = newNode;
		                       }
		                  }
		             }
		             // moving up to in TreeView if end tag is encountered
		             else if (reader.NodeType == XmlNodeType.EndElement)
		             {
		                  if (reader.Name == TAGNODE)
		                  {
		                           parentNode = parentNode.Parent;
		                  }
		             }
		             else if (reader.NodeType == XmlNodeType.XmlDeclaration)
		             { 
		                  //Ignore Xml Declaration                    
		             }
		             else if (reader.NodeType == XmlNodeType.None)
		             {
		                  return;
		             }
		             else if (reader.NodeType == XmlNodeType.Text)
		             {
		                  parentNode.Nodes.Add(reader.Value);
		             }
		    
		        }
			}
			finally
			{
				// enabling redrawing of treeview after all nodes are added
		        treeView.EndUpdate();      
		        reader.Close(); 
			}
			
			MainForm.libClipsRoot.ImageIndex = 
            MainForm.libClipsRoot.SelectedImageIndex = MainForm.ICON_CLIP_ANIM;
			
			MainForm.libClipsLibrary.ImageIndex = 
            MainForm.libClipsLibrary.SelectedImageIndex = MainForm.ICON_FOLDER;
			
			MainForm.libBitmap.ImageIndex = MainForm.libBitmapSource.ImageIndex =
			MainForm.libBitmap.SelectedImageIndex = MainForm.libBitmapSource.SelectedImageIndex = MainForm.ICON_BITMAP;
			
			cc = null;
		}
        
        /*
         * --------------------------------------------------------------------------------------------
         */
        public static string Bitmap_Path = null;
        public static List<Clip> Modules    = null;
        public static List<Clip> Frames     = null;
        public static List<Clip> Animations = null;
        
        /*
         * ExportBegin
         */
        public static void ExportBegin ()
        {
            if (Modules != null)
            {
                Utils.MsgBox("Did you use 'ExportBegin' without 'ExportEnd'?");
                return;
            }
            
            Bitmap_Path = bitmap_path;
            Modules = new List<Clip>();
            Frames = new List<Clip>();
            Animations = new List<Clip>();
            
            ExportBuildLists(MainForm.libClipsLibrary.Nodes);
        }
        
        /*
         * ExportEnd
         */
        public static void ExportEnd ()
        {
            Modules = null;
            Frames = null;
            Animations = null;
        }
        
        /*
         * ExportBuildLists
         */
        private static void ExportBuildLists(TreeNodeCollection nodesCollection)
  		{
            int i = 0;
            Clip _clip = null;
            
        	for(i = 0; i < nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            
	            if(node.Tag != null)
	            {
	                _clip = (Clip)node.Tag;
	                
	                if (_clip.usebitmap)
	                {
	                    Modules.Add(_clip);
	                }
	                else if (_clip.type == Workspace.TYPE_CLIP)
	                {
	                    Frames.Add(_clip);
	                }
	                else if (_clip.type == Workspace.TYPE_ANIMCLIP)
	                {
	                    Animations.Add(_clip);
	                }
	            }
	            if (node.Nodes.Count > 0)
				{
					ExportBuildLists(node.Nodes);
				}
			}
		}
        
        /*
         * SaveNodes
         */
        /*private static void SaveNodesXML(TreeNodeCollection nodesCollection, 
					XmlTextWriter textWriter)
  		{
        	for(int i = 0; i < nodesCollection.Count; i++)
			{
	            TreeNode node = nodesCollection[i];
	            textWriter.WriteStartElement(TAGNODE);
	            
	            if(node.Tag != null)
	            {
	            	textWriter.WriteAttributeString(TAGNAMEATT, ((Clip)node.Tag).name);
	            	textWriter.WriteAttributeString(TAGTYPEATT, ((Clip)node.Tag).type.ToString());
	            	
	            	textWriter.WriteAttributeString(TAGXATT, ((Clip)node.Tag).r.X.ToString());
	            	textWriter.WriteAttributeString(TAGYATT, ((Clip)node.Tag).r.Y.ToString());
	            	textWriter.WriteAttributeString(TAGWATT, ((Clip)node.Tag).r.Width.ToString());
	            	textWriter.WriteAttributeString(TAGHATT, ((Clip)node.Tag).r.Height.ToString());
	            }
	            // add other node properties to serialize here  
	            if (node.Nodes.Count > 0)
				{
					SaveNodes(node.Nodes, textWriter);
				}
				textWriter.WriteEndElement();
			}
		}*/

        /*
         * ExportXML
         */
        /*public static void ExportXML (string name)
        {
        	XmlTextWriter textWriter = new XmlTextWriter(name, 
                                     System.Text.Encoding.ASCII);
			
        	// writing the xml declaration tag
			textWriter.WriteStartDocument();
			// textWriter.WriteRaw("\r\n");
			// writing the main tag that encloses all node tags
			textWriter.WriteStartElement("Sprite");
			
			textWriter.WriteAttributeString(TAGBITMAPATT, bitmap_path);
			
			{
				// save the nodes, recursive method
				textWriter.WriteStartElement("Library");
				SaveNodesXML(MainForm.libClipsLibrary.Nodes, textWriter);
				textWriter.WriteEndElement();
			}
			{
				// save the nodes, recursive method
				textWriter.WriteStartElement("_root");
				SaveNodesXML(MainForm.libClipsRoot.Nodes, textWriter);
				textWriter.WriteEndElement();
			}
       
			textWriter.WriteEndElement();
        	 
       		textWriter.Close();
        }*/
	}
}
